package org.gcb.core.sandbox;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Point;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.DropMode;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JToolTip;
import javax.swing.SwingConstants;
import javax.swing.TransferHandler;
import org.gcb.core.model.Item;
import org.gcb.core.model.Toon;
import org.gcb.core.ui.Utilities;
import org.gcb.core.windows.BackpackTopComponent;
import org.gcb.core.windows.DefensesTopComponent;
import org.gcb.core.windows.EquipmentTopComponent;
import org.gcb.core.windows.SkillsTopComponent;
import org.gcb.core.windows.ToonSandboxTopComponent;
import org.openide.util.ImageUtilities;
import org.openide.util.LookupEvent;
import org.openide.windows.WindowManager;

/**
 *
 * @author Jason
 */
public class JSlot extends JPanel implements SlotListener, SwingConstants, MouseMotionListener{

    protected boolean dragEnabled;
//    private static final Logger logger = LoggerFactory.getLogger(JSlot.class);
    private final String resourceString;
    private ImageIcon imageIcon;
    private Item item;
    private SlotModel<Item> model;
    private transient DropLocation dropLocation;
    private DragSource dragSource;
    private DragGestureListener dgListener;
    private DragSourceListener dsListener;

    @Override
    public void mouseDragged(MouseEvent e) {
	this.getTransferHandler().exportAsDrag(this, e, DnDConstants.ACTION_MOVE);
    }

    @Override
    public void mouseMoved(MouseEvent e) {

    }
    public static final class DropLocation extends TransferHandler.DropLocation {

	public DropLocation(Point dropPoint) {
	    super(dropPoint);
	}

    }

    public JSlot(ImageIcon imageIcon) {
	this.imageIcon = imageIcon;
	resourceString = null;
    }

    public JSlot(String resourceString) {
	this(resourceString, null);
    }

    public JSlot(String resourceString, SlotModel<Item> model) {
	this.resourceString = resourceString;
	init(model);
    }

    public JSlot(SlotModel<Item> sm) {
	this(null, sm);
    }

    private void init(SlotModel<Item> model) {
	if (model==null) {
	    model = createDefaultSlotModel();
	}
	setModel(model);
	updateUI();
	addMouseMotionListener(this);
	this.dragSource = DragSource.getDefaultDragSource();
	this.dgListener = new JSlotDragGestureListener();
	this.dsListener = new JSlotDragSourceListener();
	this.dragSource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this.dgListener);
	setPreferredSize(new Dimension(getModel().getItem().getIcon().getIconWidth(), getModel().getItem().getIcon().getIconHeight()));
    }

    public Item getType() {
	return getModel().getItem();
    }

    public void setType(Item type) {
	getModel().setItem(type);
    }

    public boolean isEmpty() {
	return getModel().isEmpty();
    }

    public SlotModel<Item> getModel() {
	return model;
    }

    public void setModel(SlotModel<Item> model) {
	if (model==null) {
	    throw new IllegalArgumentException("Cannot set a null SlotModel");
	}
	if (this.model!=model) {
	    SlotModel<Item> oldModel = this.model;
	    if (oldModel != null) {
		oldModel.removeSlotListener(this);
	    }
	    this.model = model;
	    model.addSlotListener(this);
	    //fire model event change
	    firePropertyChange("model", oldModel, model);
	}
    }

    public boolean getDragEnabled() {
	return dragEnabled;
    }

    public void setDragEnabled(boolean b) {
        if (b && GraphicsEnvironment.isHeadless()) {
            throw new HeadlessException();
        }
	dragEnabled = b;
    }

//    public final DropMode getDropMode() {
//        return DropMode.ON;
//    }
//
//    public final DropLocation getDropLocation() {
//        return dropLocation;
//    }

    @Override
    protected void paintComponent(Graphics g) {
	super.paintComponent(g);
	if (model.isEmpty()) {
	    if (imageIcon==null) {
		g.drawImage(ImageUtilities.loadImage(resourceString), 2, 2, this);
	    } else {
		g.drawImage(imageIcon.getImage(), 2, 2, imageIcon.getImageObserver());
	    }
	} else {
	    g.drawImage(ImageUtilities.icon2Image(model.getItem().getIcon()), 2, 2, this);
	}
    }

    protected SlotModel<Item> createDefaultSlotModel() {
	Item item = new Item(ImageUtilities.image2Icon(ImageUtilities.loadImage(resourceString)), "Empty Slot");
	return new DefaultSlotModel<Item>(item);
    }

    @Override
    public void slotChanged(SlotModelEvent sme) {
//	logger.debug(sme.toString());
	getModel().getItem();
	int dumdum = 0;
        LookupEvent event = new LookupEvent(WindowManager.getDefault().findTopComponent("ToonListingTopComponent").getLookup().lookupResult(Toon.class));
        Utilities.updateUI(event, BackpackTopComponent.findInstance(), SkillsTopComponent.findInstance(), DefensesTopComponent.findInstance(), EquipmentTopComponent.findInstance(), ToonSandboxTopComponent.findInstance());
	repaint();
    }

    @Override
    protected void processMouseEvent(MouseEvent e) {
	super.processMouseEvent(e);
    }

    @Override
    protected void processMouseMotionEvent(MouseEvent e) {
	super.processMouseMotionEvent(e);
    }

    @Override
    public JToolTip createToolTip() {
	return super.createToolTip();
    }
}
